基于阈值的图像分割方法以及Python实现 您所在的位置:网站首页 opencv 二值化阈值选取 基于阈值的图像分割方法以及Python实现

基于阈值的图像分割方法以及Python实现

2024-06-02 08:18| 来源: 网络整理| 查看: 265

阈值分割定义

阈值分割法可以说是图像分割中的经典方法,它利用图像中要提取的目标与背景在灰度上的差异,通过设置阈值来把像素分成若干类,从而实现目标与背景的分离。 根据不同的分类方法,阈值分割有以下几种方法:

固定阈值分割迭代阈值分割大津法OTSU自适应阈值分割 一、固定阈值分割法

将灰度值大于某一阈值的像素点设置为255,而小于等于该阈值的点设置为0。

函数说明:

cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst

函数 threshold() 可以将灰度图像转换为二值图像,图像完全由像素 0 和 255 构成,呈现出只有黑白两色的视觉效果。

参数说明:

scr:变换操作的输入图像,nparray 二维数组,必须是单通道灰度图像!thresh:阈值,取值范围 0~255maxval:填充色,取值范围 0~255,一般取 255type:变换类型 cv2.THRESH_BINARY:大于阈值时置 255,否则置 0 cv2.THRESH_BINARY_INV:大于阈值时置 0,否则置 255 cv2.THRESH_TRUNC:大于阈值时置为阈值 thresh,否则不变(保持原色) cv2.THRESH_TOZERO:大于阈值时不变(保持原色),否则置 0 cv2.THRESH_TOZERO_INV:大于阈值时置 0,否则不变(保持原色) cv2.THRESH_OTSU:使用 OTSU 算法选择阈值 返回值 retval:返回二值化的阈值返回值 dst:返回阈值变换的输出图像

代码如下

import cv2 import matplotlib.pyplot as plt img = cv2.imread('./data/image.jpg', flags=1) # 读取彩色图像 img_gray = cv2.imread('./data/image.jpg', flags=0) # 读取灰度图像 ret, th = cv2.threshold(img_gray, 120, 255, cv2.THRESH_BINARY) # 用cv2实现固定阈值分割 plt.subplot(131), plt.imshow(img) plt.title('Original Image'), plt.xticks([]), plt.yticks([]) plt.subplot(132), plt.imshow(img_gray, cmap='gray') plt.title('Gray Image'), plt.xticks([]), plt.yticks([]) plt.subplot(133), plt.imshow(th, cmap='gray') plt.title('Fix Image'), plt.xticks([]), plt.yticks([]) plt.show()

输出结果如下 在这里插入图片描述

二、迭代阈值分割 1 直方图

灰度直方图反映了图像中的灰度分布规律,直观地表现了图像中各灰度级的占比,很好地体现出图像的亮度和对比度信息:灰度图分布居中说明亮度正常,偏左说明亮度较暗,偏右表明亮度较高;狭窄陡峭表明对比度降低,宽泛平缓表明对比度较高。 横坐标代表灰度值的取值区间,纵坐标代表每一像素值在图像中的像素总数或者所占的百分比。

函数说明

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) → hist

函数 cv2.calcHist 可以计算一维直方图或二维直方图,函数的参数 images, channels, histSize, ranges 在计算一维直方图时也要带 [] 号。

参数说明

images:输入图像,用 [] 括号表示

channels: 直方图计算的通道,用 [] 括号表示

mask:掩模图像,一般置为 None

histSize:直方柱的数量,一般取 256

ranges:像素值的取值范围,一般为 [0,256]

返回值 hist:返回每一像素值在图像中的像素总数,形状为 (histSize,1)

代码如下

import cv2 import matplotlib.pyplot as plt import numpy as np img = cv2.imread("./data/image.jpg", flags=0) # flags=0 读取为灰度图像 histCV = cv2.calcHist([img], [0], None, [256], [0, 256]) # OpenCV 函数 cv2.calcHist plt.figure(figsize=(10, 3)) plt.subplot(121), plt.imshow(img, cmap='gray', vmin=0, vmax=255), plt.title("Original"), plt.axis('off') plt.subplot(122, xticks=[], yticks=[]), plt.axis([0, 255, 0, np.max(histCV)]) plt.bar(range(256), histCV[:, 0]), plt.title("Gray Hist") plt.show()

输出结果如下 在这里插入图片描述

2 原理 设置初始阈值 T T T,通常可以设为图像的平均灰度;用灰度阈值 T T T分割图像:灰度值小于 T T T的所有像素集合 G 1 G_1 G1​和大于等于 T T T的所有像素集合 G 2 G_2 G2​;分别计算 G 1 G_1 G1​、 G 2 G_2 G2​的平均灰度值 m 1 m_1 m1​、 m 2 m_2 m2​;求出新的灰度阈值 T = m 1 + m 2 2 T=\frac{m_1+m_2}{2} T=2m1​+m2​​重复步骤(2)~(4),直到阈值变化小于设定值。

代码如下

import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread("./data/image.jpg", flags=0) deltaT = 1 # 预定义值 histCV = cv2.calcHist([img], [0], None, [256], [0, 256]) # 灰度直方图 grayScale = range(256) # 灰度级 [0,255] totalPixels = img.shape[0] * img.shape[1] # 像素总数 totalGary = np.dot(histCV[:, 0], grayScale) # 内积, 总和灰度值 T = round(totalGary / totalPixels) # 平均灰度 while True: numG1, sumG1 = 0, 0 for i in range(T): # 计算 C1: (0,T) 平均灰度 numG1 += histCV[i, 0] # C1 像素数量 sumG1 += histCV[i, 0] * i # C1 灰度值总和 numG2, sumG2 = (totalPixels - numG1), (totalGary - sumG1) # C2 像素数量, 灰度值总和 T1 = round(sumG1 / numG1) # C1 平均灰度 T2 = round(sumG2 / numG2) # C2 平均灰度 Tnew = round((T1 + T2) / 2) # 计算新的阈值 print("T={}, m1={}, m2={}, Tnew={}".format(T, T1, T2, Tnew)) if abs(T - Tnew)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有